package com.sikaryofficial.qrcode.manager;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson2.JSONObject;
import com.sikaryofficial.common.core.constant.CacheBusinessConstants;
import com.sikaryofficial.common.core.domain.R;
import com.sikaryofficial.common.redis.service.RedisService;
import com.sikaryofficial.qrcode.domain.mongo.QrUserDetailMongo;
import com.sikaryofficial.qrcode.service.ProductQrMongoService;
import com.sikaryofficial.qrcode.service.QrUserDetailMongoService;
import com.sikaryofficial.qrcode.service.brand.cache.BrandTasteCacheService;
import com.sikaryofficial.qrcode.util.ProductQrUtil;
import com.sikaryofficial.system.api.RemoteProductService;
import com.sikaryofficial.system.api.domain.ProductQr;
import com.sikaryofficial.system.api.model.ip.IpLocationVO;
import com.sikaryofficial.system.api.model.ip.IpOutputInfoVO;
import com.sikaryofficial.system.api.model.product.BrandTasteDTO;
import com.sikaryofficial.system.api.model.product.ProductStatisticsReq;
import com.sikaryofficial.system.api.model.qrcode.QrCacheVO;
import com.sikaryofficial.system.api.model.skeremote.BrandSecurityResp;
import com.sikaryofficial.system.api.model.skeremote.BrandTasteSecurityReq;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author : qinjinyuan
 * @desc : 内容管理服务
 * @date : 2023/10/30 15:39
 */
@Service
@Slf4j
@RefreshScope
@SuppressWarnings(value = "unchecked")
public class QrSkeCallbackManager {
    private static final String IP_SERVICE_URL = "http://ip-api.com/json/{0}?lang=zh-CN";
    @Autowired
    private BrandTasteCacheService brandTasteCacheService;
    @Autowired
    private ProductQrMongoService productQrService;

    @Autowired
    private QrUserDetailMongoService qrUserDetailMongoService;
    @Autowired
    private RemoteProductService remoteProductService;

    @Autowired
    private RedisService redisService;
    @Value("${hismk.qrcode.ske.remoteSkeNoticeUrl}")
    private String remoteSkeNoticeUrl;
    @Value("${hismk.qrcode.ske.appSecret}")
    private String  appSecret;

    @Async("asyncTaskExecutor")
    public void callbackForUserDetail(String ip, String param, Long userId,String userAgent) {
        QrUserDetailMongo qrUserDetailMongo = QrUserDetailMongo.builder()
                .param(param)
                .ip(ip)
                .userId(userId)
                .build();
        R<IpLocationVO> ipLocationVOR = remoteProductService.getCountryArea(ip);
        if (Objects.nonNull(ipLocationVOR) && R.isSuccess(ipLocationVOR) && Objects.nonNull(ipLocationVOR.getData())) {
            qrUserDetailMongo.setArea(ipLocationVOR.getData().getCity());
            qrUserDetailMongo.setCity(ipLocationVOR.getData().getCity());
            qrUserDetailMongo.setCountryCode(ipLocationVOR.getData().getCountryCode());
            qrUserDetailMongo.setCountryName(ipLocationVOR.getData().getCountryName());
        }
        qrUserDetailMongo.setUserAgent(userAgent);
        // 1、查询产品信息
        Integer productShortId = Integer.parseInt(param.split(ProductQrUtil.PARAM_SPLIT_KEY)[0]);
        BrandTasteDTO brandTasteDTO = brandTasteCacheService.getSignBrandTasteByShortId(productShortId);
        if(Objects.nonNull(brandTasteDTO)){
            qrUserDetailMongo.setBrandTasteId(brandTasteDTO.getBrandTasteId());
            qrUserDetailMongo.setProductShortId(productShortId);
            qrUserDetailMongo.setDeletedVersion(0L);
        }
        qrUserDetailMongo.setCreatedTime(new Date());
        qrUserDetailMongoService.save(qrUserDetailMongo);
    }

    /**
     * 1、根据IP查询相关字段： 国家、城市
     * 2、查询产品相关字段： 品牌 + 口味（默认） + 型号
     * 3、查询扫码缓存数据
     *
     * @param param
     */

    @Async("asyncTaskExecutor")
    public void callback(BrandTasteSecurityReq param) {
        BrandSecurityResp res = new BrandSecurityResp();
        // 1、查询产品信息
        String p = param.getP();
        res.setCode(p);
        Integer productShortId = Integer.parseInt(p.split(ProductQrUtil.PARAM_SPLIT_KEY)[0]);
        BrandTasteDTO brandTasteDTO = brandTasteCacheService.getSignBrandTasteByShortId(productShortId);
        res.setBrandNo(brandTasteDTO.getBrandNo());
        res.setModel(brandTasteDTO.getModel());
        res.setTasteName(brandTasteDTO.getTasteName());
        // 2、获取最新扫码统计次数
        String cacheKey = MessageFormat.format(CacheBusinessConstants.SCAN_QRCODE_NUM_CACHE, param);
        QrCacheVO qrCacheVO = redisService.getCacheObject(cacheKey);
        if (Objects.isNull(qrCacheVO)) {
            ProductQr productQr = productQrService.getProductQr(p);
            qrCacheVO = new QrCacheVO();
            qrCacheVO.setScanCodeNum(productQr.getScanCodeNum());
            qrCacheVO.setUpdatedTime(productQr.getUpdatedTime());
        }
        res.setScanCodeNum(qrCacheVO.getScanCodeNum()+"");
        res.setFistTime(LocalDateTimeUtil.format(LocalDateTimeUtil.of(qrCacheVO.getUpdatedTime()), DatePattern.NORM_DATETIME_PATTERN));
        // 3、根据IP获取相关信息
        res.setIp(param.getIpAddress());
        IpOutputInfoVO ipOutputInfoVO = callIpService(param.getIpAddress());
        if (Objects.nonNull(ipOutputInfoVO)) {
            res.setCity(ipOutputInfoVO.getCity());
            res.setCountry(ipOutputInfoVO.getCountry());
            res.setRegion(ipOutputInfoVO.getRegion());
        }
        callSkeNoticeService(res);

        // 将统计数据汇总到mysql 数据库
        ProductStatisticsReq productStatisticsReq = new ProductStatisticsReq();
        productStatisticsReq.setBrandTasteId(brandTasteDTO.getBrandTasteId());
        // 此处应该是统计
        productStatisticsReq.setNormalScanCount(productQrService.countScanCodeNumById(brandTasteDTO.getBrandTasteId()));
        remoteProductService.normalSave(productStatisticsReq);
    }

    /**
     * 调用ip服务
     * @param ipAddress
     * @return
     */
    public IpOutputInfoVO callIpService(String ipAddress) {
        if (CharSequenceUtil.isBlank(ipAddress)) {
            return null;
        }
        // 从缓存获取 24.48.0.1
        String cacheKey = MessageFormat.format(CacheBusinessConstants.HISMK_IP_SERVICE_REQUEST_CACHE, ipAddress);
        IpOutputInfoVO result = redisService.getCacheObject(cacheKey);
        if(Objects.nonNull(result)){
            return result;
        }
        String getUrl = MessageFormat.format(IP_SERVICE_URL, ipAddress);
        try {
            //链式构建请求
            String result2 = HttpRequest.get(getUrl)
                    .timeout(20000)//超时，毫秒
                    .execute().body();
            if (CharSequenceUtil.isNotBlank(result2)) {
                result = JSONObject.parseObject(result2, IpOutputInfoVO.class);
                redisService.setCacheObject(cacheKey, result, 24L,TimeUnit.HOURS);
                return result;
            }
        } catch (Exception e) {
            log.error("callIpService error.{}",e);
        }
        return null;
    }

    /**
     * ske远程 回调通知服务
     *
     * @param res
     * @return
     */
    public void callSkeNoticeService( BrandSecurityResp res) {
        res.setSuccess("1");
        long timestamp = System.currentTimeMillis();
        String body = JSONObject.toJSONString(res);
        log.info("callSkeNoticeService,param:{}",body);
        String md5Str = DigestUtil.md5Hex(body + timestamp + appSecret);
        String getUrl = remoteSkeNoticeUrl.concat("?timestamp=").concat(timestamp+"")
                .concat("&sign=").concat(md5Str);
        log.info("callSkeNoticeService,getUrl:{}",getUrl);
        try {
            //链式构建请求
            String result2 = HttpRequest.post(getUrl)
                    .header(Header.CONTENT_TYPE, "application/json") //头信息，多个头信息多次调用此方法即可
                    .timeout(20000)//超时，毫秒
                    .body(body)
                    .execute().body();
            if (CharSequenceUtil.isNotBlank(result2)) {
                /**
                 * {
                 *     "code": 0,       // 状态码：1成功0失败
                 *     "show": 0,       // 忽略
                 *     "msg": "string", // 返回消息提示
                 *     "data": []
                 * }
                 */
                JSONObject obj =  JSONObject.parseObject(result2, JSONObject.class);
                log.info("call ske service success.info{}", obj);
            }
        } catch (Exception e) {
            log.error("callSkeNoticeService error.{}",e);
        }
    }
}
